package Control;

import Control.*;
import Modelo.Ataque;
import Modelo.AtaqueEspecial;
import Modelo.Defensa;
import Modelo.DefensaEspecial;
import Modelo.PersonajeDTO;
import Modelo.Turno;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.Point;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;
import java.util.ArrayList;
import javax.swing.ImageIcon;
import javax.swing.JOptionPane;
import javax.swing.JProgressBar;
import javax.swing.Timer;
import vista.VentanaJuego;
import vista.VentanaPrincipal;
import vista.AutoDismiss;

public final class ControlVentanaJuego implements ActionListener {

    // <editor-fold defaultstate="collapsed" desc="Atributos">
    public VentanaJuego vista = null;
    ControlAudioJuego audio = new ControlAudioJuego();
    private Turno turno = Turno.ATACA_BUENO;
    private PersonajeDTO bueno;
    private PersonajeDTO malo;
    private ArrayList<PersonajeDTO> malos;
    private int rounds;
    private int rActual = 1;
    private int tiempo = 1;
    private double dañoActual;
    private AutoDismiss ad = null;
    private ControlVentanaPrincipal cvp = null;
    private ImageIcon victoria = new ImageIcon("Imagenes/Victoria.png");
    private ImageIcon derrota = new ImageIcon("Imagenes/Derrota.png");
    private ImageIcon atenea = new ImageIcon("Imagenes/Atenea.jpg");
    private boolean ataqueExitoso = false, pierdeTurno = false;
    
    // </editor-fold>
    // <editor-fold defaultstate="collapsed" desc="Constructores">
    public ControlVentanaJuego() {
        vista = new VentanaJuego();
        establecerParametrosVentana();
        vincularEventos();
        this.vista.Lbl_Round.setText("Round: " + rActual);
        this.vista.Lbl_Estado_Bueno.setText("Ataca");
        this.vista.Lbl_Estado_Malo.setText("Espera");
    }

    public ControlVentanaJuego(ControlVentanaPrincipal cvp, PersonajeDTO bueno, ArrayList<PersonajeDTO> malos) {
        this();
        
        this.cvp = cvp;
        this.bueno = bueno;
        this.malos = malos;
        this.malo = malos.get(0);
        this.rounds = malos.size();
        cargarPersonajeBueno(bueno);
        cargarPersonajeMalo(malo);
    }

    // </editor-fold>
    // <editor-fold defaultstate="collapsed" desc="Metodos">
    // <editor-fold defaultstate="collapsed" desc="Interfaz"> 
    private void establecerParametrosVentana() {
        // parámetros de la ventana juego
        this.vista.setLocationRelativeTo(null);
        this.vista.setVisible(true);
    }

    public void cargarPersonajeBueno(PersonajeDTO personaje) {
        Image img = personaje.getImagen().getImage();
        Image newimg = img.getScaledInstance(181, 164, java.awt.Image.SCALE_SMOOTH);
        this.vista.Lbl_PersonajeBueno.setIcon(new ImageIcon(newimg));
        iniciaBarraVida(this.vista.PgsBar_Bueno, personaje);
        this.vista.Lbl_NombreBueno.setText(personaje.getNombre());
    }

    public void cargarPersonajeMalo(PersonajeDTO personaje) {
        Image img = personaje.getImagen().getImage();
        Image newimg = img.getScaledInstance(181, 164, java.awt.Image.SCALE_SMOOTH);
        this.vista.Lbl_PersonajeMalo.setIcon(new ImageIcon(newimg));
        iniciaBarraVida(this.vista.PgsBar_Malo, personaje);
        this.vista.Lbl_NombreMalo.setText(personaje.getNombre());
    }

    private void iniciaBarraVida(JProgressBar barra, PersonajeDTO personaje) {
        barra.setMinimum(0);
        double vida = personaje.getNivelVida();
        barra.setMaximum((int) vida);
        barra.setStringPainted(true);
        barra.setString("" + vida);
        barra.setValue((int) vida);
    }
    // </editor-fold>

    // <editor-fold defaultstate="collapsed" desc="Control"> 
    private void vincularEventos() {
        this.vista.Btn_SigTurno.addActionListener(this);
    }

    // si alguien perdió, el bueno o el malo
    private boolean alguienMuere() {
        if (this.vista.PgsBar_Bueno.getValue() == 0) {
            perderJuego();
            return true;
        }

        if (this.vista.PgsBar_Malo.getValue() == 0) {
            cambioDeOponente();
            return true;
        }

        return false;
    }

    private void ganarJuego() {
        JOptionPane.showMessageDialog(this.vista,
                "Felicidades ha ganado el juego. Se redirige a la ventana de inicio...",
                "Victoria",
                JOptionPane.PLAIN_MESSAGE,
                victoria);
        this.vista.dispose();
        this.cvp.vista.setVisible(true);
    }

    private void perderJuego() {
        if (bueno.getNombre().equals("Caballeros de bronce")) {
            int numero = ControlPersonajes.aleatorio(0, 100);
            if (numero <= 50) {
                this.vista.PgsBar_Bueno.setValue(500);
                this.vista.PgsBar_Bueno.setString("" + 500);
                JOptionPane.showMessageDialog(this.vista,
                        "La Diosa Atenea revive a los caballeros de bronce... les recupera la mitad de su vida.",
                        "Atenea",
                        JOptionPane.PLAIN_MESSAGE,
                        atenea);
                return;
            }
        }

        JOptionPane.showMessageDialog(this.vista,
                "Lo sentimos ha perdido el juego. Se redirige a la ventana de inicio...",
                "Derrota",
                JOptionPane.PLAIN_MESSAGE,
                derrota);
        this.vista.dispose();
        this.cvp.vista.setVisible(true);
    }

    private void cambioDeOponente() {
        this.malos.remove(0);
        if (malos.isEmpty()) {
            ganarJuego();
        } else {
            ad = new AutoDismiss(vista, "Cambio de capítulo... Se recuperan 200 de vida...");
            // nuevo personaje malo
            this.malo = malos.get(0);
            cargarPersonajeMalo(malo);

            // +200 de superar capitulo
            double vida = this.vista.PgsBar_Bueno.getValue() + 200;
            vida = (vida <= 1000) ? vida : 1000;
            this.vista.PgsBar_Bueno.setValue((int) vida);
            this.vista.PgsBar_Bueno.setString("" + vida);

            // siempre comienza atacando el bueno
            this.turno = Turno.ATACA_BUENO;

            // incrementa el round
            
            this.vista.Lbl_Round.setText("Round: " + ++rActual);
        }
    }

    private void eligeTurno() {
        this.vista.Lbl_Estado_Bueno.setText("Espera");
        this.vista.Lbl_Estado_Malo.setText("Espera");

        switch (turno) {
            case ATACA_BUENO:
                this.vista.Lbl_Estado_Bueno.setText("Ataca");
                atacaBueno();
                break;
            case DEFIENDE_MALO:
                this.vista.Lbl_Estado_Malo.setText("Defiende");
                defiendeMalo();
                break;
            case ATACA_MALO:
                this.vista.Lbl_Estado_Malo.setText("Ataca");
                atacaMalo();
                break;
            case DEFIENDE_BUENO:
                this.vista.Lbl_Estado_Bueno.setText("Defiende");
                defiendeBueno();
                break;
        }
        this.vista.Lbl_Tiempo.setText("Tiempo: " + tiempo++);
        //this.mostrarMensaje(ControlPersonajes.mensaje);
        sigTurno();

        alguienMuere();
    }

    private void sigTurno() {
        switch (turno) {
            case ATACA_BUENO:
                turno = Turno.DEFIENDE_MALO;
                break;
            case DEFIENDE_MALO:
                turno = Turno.ATACA_MALO;
                break;
            case ATACA_MALO:
                turno = Turno.DEFIENDE_BUENO;
                break;
            case DEFIENDE_BUENO:
                turno = Turno.ATACA_BUENO;
                break;
        }
    }

    private void atacaBueno() {
        this.ataqueExitoso = pierdeTurno = false;
        Ataque ataque = bueno.eligeAtaque();
        String texto;
        int vida = this.vista.PgsBar_Bueno.getValue();
        if (ataque == null) {
            texto = ControlPersonajes.textoAtaque(false, tiempo, bueno, ataque, vida);
            sigTurno();
        } else {
            procesarAtaque(ataque.getAtaqueEspecial(), true);
            texto = ControlPersonajes.textoAtaque(true, tiempo, bueno, ataque, vida);
            this.dañoActual = ataque.getDaño();
        }

        //audio.reproducirSonido("C:/Users/Edwin/Desktop/trunk/CaballerosDelZodiaco/src/Sound/attack2.wav");
        this.vista.Txt_Bueno.append(texto);
    }

    private void defiendeMalo() {
        Defensa defensa = malo.escogerDefensa();
        double dañoRecibido = this.dañoActual - defensa.getResistencia();
        dañoRecibido = (dañoRecibido < 0) ? 0 : dañoRecibido;
        double vida = this.vista.PgsBar_Malo.getValue() - dañoRecibido;
        vida = (vida > 0) ? vida : 0;
        this.vista.PgsBar_Malo.setValue((int) vida);
        this.vista.PgsBar_Malo.setString("" + vida);
        String texto = ControlPersonajes.textoDefensa(tiempo, malo, defensa, dañoRecibido, (int) vida);
        this.vista.Txt_Malo.append(texto);
        procesarDefensa(defensa.getDefensaEspecial(), false);

        this.ataqueExitoso = (dañoRecibido > 0) ? true : false;
        if (ataqueExitoso && pierdeTurno) {
            this.sigTurno();
            this.sigTurno();
        }
    }

    private void atacaMalo() {
        this.ataqueExitoso = pierdeTurno = false;
        Ataque ataque = malo.eligeAtaque();
        String texto;
        int vida = this.vista.PgsBar_Malo.getValue();
        if (ataque == null) {
            texto = ControlPersonajes.textoAtaque(false, tiempo, malo, ataque, vida);
            sigTurno();
        } else {
            texto = ControlPersonajes.textoAtaque(true, tiempo, malo, ataque, vida);
            this.dañoActual = ataque.getDaño();
            procesarAtaque(ataque.getAtaqueEspecial(), false);
        }
        // audio.reproducirSonido("C:/Users/Edwin/Desktop/trunk/CaballerosDelZodiaco/src/Sound/attack3.wav");
        this.vista.Txt_Malo.append(texto);
    }

    private void defiendeBueno() {
        Defensa defensa = bueno.escogerDefensa();
        procesarDefensa(defensa.getDefensaEspecial(), true);
        double dañoRecibido = this.dañoActual - defensa.getResistencia();
        dañoRecibido = (dañoRecibido < 0) ? 0 : dañoRecibido;
        double vida = this.vista.PgsBar_Bueno.getValue() - dañoRecibido;
        vida = (vida > 0) ? vida : 0;
        this.vista.PgsBar_Bueno.setValue((int) vida);
        this.vista.PgsBar_Bueno.setString("" + vida);

        String texto = ControlPersonajes.textoDefensa(tiempo, bueno, defensa, dañoRecibido, (int) vida);
        this.vista.Txt_Bueno.append(texto);
        this.ataqueExitoso = (dañoRecibido > 0) ? true : false;

        if (ataqueExitoso && pierdeTurno) {
            this.sigTurno();
            this.sigTurno();
        }
    }

    private void procesarAtaque(AtaqueEspecial ataqueEspecial, boolean bueno) {
        switch (ataqueEspecial) {
            case NINGUNO:
                break;
            case ADVERSARIO_PIERDE_TURNO:
                pierdeTurno = true;
                break;
            case RECUPERA_200_VIDA:
                recuperarVida(200, bueno);
                break;
            case CANTIDAD_SOLDADOS_05:
                int vida = this.vista.PgsBar_Malo.getValue();
                this.dañoActual = (vida * 0.5);
                this.vista.Txt_Malo.append("\n----------Daño del ataque: " + dañoActual + "------------\n");
                break;
            case CANTIDAD_SOLDADOS_1:
                vida = this.vista.PgsBar_Malo.getValue();
                this.dañoActual = (vida);
                this.vista.Txt_Malo.append("\n----------Daño del ataque: " + dañoActual + "------------\n");
                break;
            case CANTIDAD_SOLDADOS_2:
                vida = this.vista.PgsBar_Malo.getValue();
                this.dañoActual = (vida * 2);
                this.vista.Txt_Malo.append("\n----------Daño del ataque: " + dañoActual + "------------\n");
                break;
        }
    }

    private void procesarDefensa(DefensaEspecial defensaEspecial, boolean bueno) {
        switch (defensaEspecial) {
            case NINGUNA:
                break;
            case RECUPERA_100_VIDA:
                recuperarVida(100, bueno);
                break;
            case CONTRAATAQUE_250:
                // se sabe que es Radamán, sólo si sigue vivo después del ataque
                if (this.vista.PgsBar_Malo.getValue() > 0) {
                    int value = this.vista.PgsBar_Bueno.getValue();
                    value = (value - 250) >= 0 ? value - 250 : 0;
                    this.vista.PgsBar_Bueno.setValue(value);
                    this.vista.PgsBar_Bueno.setString("" + value);
                }
                break;
        }
    }

    void recuperarVida(int monto, boolean bueno) {
        if (bueno) {
            int valor = this.vista.PgsBar_Bueno.getValue();
            valor = (valor + monto) <= 1000 ? valor + monto : 1000;
            this.vista.PgsBar_Bueno.setValue(valor);
            this.vista.PgsBar_Bueno.setString("" + valor);
        } else {
            int valor = this.vista.PgsBar_Malo.getValue();
            valor = (valor + monto) <= malo.getNivelVida() ? valor + monto : (int) malo.getNivelVida();
            this.vista.PgsBar_Malo.setValue(valor);
            this.vista.PgsBar_Malo.setString("" + valor);
        }
    }

    void mostrarMensaje(String mensaje) {
        ad = new AutoDismiss(this.vista, mensaje);
    }

    // </editor-fold>
    // </editor-fold>
    // <editor-fold defaultstate="collapsed" desc="Metodos sobreEscritos">
    @Override
    public void actionPerformed(ActionEvent e) {
        if (e.getSource().equals(this.vista.Btn_SigTurno)) {
            eligeTurno();
        }
    }
    // </editor-fold>

}
